﻿using System;
using System.Collections.Generic;

namespace Gonte.Caching
{
    /// <summary>
    /// Expires the least used item when the threshold capacity is reached
    /// </summary>
    public class LruExpirationPolicy
        : ExpirationPolicy
    {
        public LruExpirationPolicy(int maximumCapacity)
        {
            maximumCapacity_ = maximumCapacity;
            queue_ = new LinkedList<string>();
        }

        #region Overridables

        public override void NotifyItemAdded(string key)
        {
            queue_.AddFirst(key);

            if (cache_.Count > maximumCapacity_) // Remove the least used item
            {
                string leastUsedKey = queue_.Last.Value;
                cache_.Remove(leastUsedKey);
                queue_.RemoveLast();
            }
        }

        public override void NotifyItemFetched(string key)
        {
            MoveToFirst(key);
        }

        public override void NotifyItemSet(string key)
        {
            MoveToFirst(key);
        }

        public override void NotifyItemRemoved(string key)
        {
            queue_.Remove(key);
        } 

        #endregion

        #region Helpers

        private void MoveToFirst(string key)
        {
            if (queue_.Count > 0
                && !key.Equals(queue_.First.Value)) // The key is not the first
            {
                queue_.Remove(key);
                queue_.AddFirst(key);
            }
        } 

        #endregion

        #region Fields

        private int maximumCapacity_;
        private LinkedList<string> queue_; 

        #endregion
    }
}
